package com.ims.web.controller.system;

import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import com.baiwang.open.entity.response.ChannelLoginEncryptconfigResponse;
import com.baiwang.open.entity.response.ChannelLoginNewexploreactivityResponse;
import com.baiwang.open.entity.response.ChannelLoginQuickuniteResponse;
import com.baiwang.open.entity.response.ChannelLoginSmscodeResponse;
import com.baiwang.open.entity.response.node.ChannelLoginEncryptconfig;
import com.baiwang.open.entity.response.node.ChannelLoginNewexploreactivity;
import com.baiwang.open.entity.response.node.ChannelLoginQuickunite;
import com.baiwang.open.entity.response.node.ChannelLoginSmscode;
import com.ims.common.constant.Constants;
import com.ims.common.core.domain.AjaxResult;
import com.ims.common.core.domain.entity.SysMenu;
import com.ims.common.core.domain.entity.SysUser;
import com.ims.common.core.domain.model.EiLoginBody;
import com.ims.common.core.domain.model.EiSmsCodeLoginBody;
import com.ims.common.core.domain.model.LoginBody;
import com.ims.common.core.domain.model.LoginUser;
import com.ims.common.exception.base.BaseException;
import com.ims.common.utils.SecurityUtils;
import com.ims.common.utils.StringUtils;
import com.ims.common.utils.sign.SM2Utils;
import com.ims.framework.web.service.SysLoginService;
import com.ims.system.domain.TSysSite;
import com.ims.system.service.ISysMenuService;
import com.ims.framework.web.service.SysPermissionService;
import com.ims.system.service.ITSysSiteService;
import com.ims.util.BaiwangUtils;
import com.ims.web.controller.common.CommonController;
import org.bouncycastle.jcajce.provider.asymmetric.ec.GMCipherSpi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 登录验证
 *
 * @author IMS
 */
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private ITSysSiteService siteService;

    @Autowired
    private SysPermissionService permissionService;

    private static final Logger log = LoggerFactory.getLogger(SysLoginController.class);
    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 数电登录方法
     *
     * @param eiLoginBody 登录信息
     * @return 结果
     */
    @PostMapping("/eiLogin")
    public AjaxResult eiLogin(@RequestBody EiLoginBody eiLoginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 获取加密配置
        ChannelLoginEncryptconfigResponse channelLoginEncryptconfigResponse = BaiwangUtils.encryptconfig();
        if(!channelLoginEncryptconfigResponse.getSuccess()){
            log.error("获取加密配置失败 {}", eiLoginBody.getTaxNo());
            return AjaxResult.error("数电登录失败!");
        }
        ChannelLoginEncryptconfig channelLoginEncryptconfig = channelLoginEncryptconfigResponse.getResponse().get(0);
        String publicKey = channelLoginEncryptconfig.getPublicKeys().get(0);
        // 密码加密
        SM2 sm2ByPublicKey = SmUtil.sm2(null, publicKey);
        //2、公钥加密
        String encryptedBase64Data = sm2ByPublicKey.encryptBcd(eiLoginBody.getDeepChar(), KeyType.PublicKey);

        ChannelLoginQuickuniteResponse response = BaiwangUtils.login(eiLoginBody.getUsername(), eiLoginBody.getTaxNo(), eiLoginBody.getAreaCode(), encryptedBase64Data);
        if(!response.getSuccess()){
            log.error("数电登录失败 {} {} {} {} {}", response.getRequestId(), eiLoginBody.getUsername(), eiLoginBody.getTaxNo(), eiLoginBody.getAreaCode(), eiLoginBody.getDeepChar());
            return AjaxResult.error("数电登录失败!");
        }
        ChannelLoginQuickunite channelLoginQuickunite = response.getResponse().get(0);
        // 批次号
        ajax.put("batchNo", channelLoginQuickunite.getBatchNo());
        // 双因子登录接口：1，无此字段即为登录成功
        ajax.put("sendMsg", channelLoginQuickunite.getSendMsg());
        // 二维码
        ajax.put("qrcode", channelLoginQuickunite.getQrcode());
        // 验证类型：短信：0 、 税务app扫码：、1 个税app扫码：2
        ajax.put("authenticationType", "0");
        // 是否登录成功
        if(StringUtils.isEmpty(channelLoginQuickunite.getSendMsg())){
            ajax.put("loginSuccess", "1");
        } else {
            if(channelLoginQuickunite.getSendMsg().equals("0")){
                ajax.put("loginSuccess", "2");
            } else {
                ajax.put("loginSuccess", "0");
            }
        }
//        ajax.put("batchNo", "123");
//        // 双因子登录接口：1，无此字段即为登录成功
//        ajax.put("sendMsg", "");
//        // 二维码
//        ajax.put("qrcode", "");
//        // 验证类型：短信：0 、 税务app扫码：、1 个税app扫码：2
//        ajax.put("authenticationType", "0");
//        // 是否登录成功
//        ajax.put("loginSuccess", "0");
        return ajax;
    }

    /**
     * 数电登短信验证码录方法
     *
     * @param eiSmsCodeLoginBody 登录信息
     * @return 结果
     */
    @PostMapping("/eiSmsCodeLogin")
    public AjaxResult eiSmsCodeLogin(@RequestBody EiSmsCodeLoginBody eiSmsCodeLoginBody)
    {
        AjaxResult ajax = AjaxResult.success();

        ChannelLoginSmscodeResponse response = BaiwangUtils.smscode(eiSmsCodeLoginBody.getSmsCode(), eiSmsCodeLoginBody.getBatchNo());
        if(!response.getSuccess()){
            log.error("数电短信登录失败 {} {} {} ", response.getRequestId(), eiSmsCodeLoginBody.getSmsCode(), eiSmsCodeLoginBody.getBatchNo());
            return AjaxResult.error("数电登录失败!");
        }
        ChannelLoginSmscode channelLoginSmscode = response.getResponse().get(0);
        // 批次号
        ajax.put("batchNo", channelLoginSmscode.getBatchNo());
        // 是否登录成功
        if(!StringUtils.isEmpty(channelLoginSmscode.getBatchNo())){
            ajax.put("loginSuccess", "1");
        } else {
            ajax.put("loginSuccess", "0");
        }
        return ajax;
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        ajax.put("siteCode", SecurityUtils.getLoginUser().getSiteCode());
        ajax.put("siteName", SecurityUtils.getLoginUser().getSiteName());
        ajax.put("taxNo", SecurityUtils.getLoginUser().getTaxNo());
        return ajax;
    }

    /**
     * 获取数电是否登录
     *
     * @return 用户信息
     */
    @GetMapping("checkEiActivity")
    public AjaxResult checkEiActivity()
    {
        AjaxResult ajaxResult = AjaxResult.success();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        TSysSite sysSite = null;
        String siteCode = loginUser.getSiteCode();
        //当前用户无法关联公司，取默认公司
        if(StringUtils.isEmpty(siteCode)){
            sysSite = siteService.getCurrentSite();
        } else {
            sysSite = siteService.selectTSysSiteByCode(siteCode);
        }
        if(Objects.isNull(sysSite)){
            return AjaxResult.error(10000,"找不到当前企业");
        }
        // 调用百望探活接口
        try {

            ChannelLoginNewexploreactivityResponse response = BaiwangUtils.exploReactivity(sysSite.getTaxNumber(), sysSite.getAreaCode());
            ChannelLoginNewexploreactivity channelLoginNewexploreactivity = response.getResponse().get(0);
            // 探活返回code
            ajaxResult.put("checkCode", channelLoginNewexploreactivity.getCheckCode());
            // checkMessage
            ajaxResult.put("checkMessage", channelLoginNewexploreactivity.getCheckMessage());
            // 探活返回code：1：跟电票连接保持中、2：账号登录其他税号、3：跟电票连接断开
            if(channelLoginNewexploreactivity.getCheckCode().equals(1)){
                // 当前登录税号
                ajaxResult.put("taxUserName", channelLoginNewexploreactivity.getTaxUserName());
                // 探活账号
                ajaxResult.put("currentTaxNo", channelLoginNewexploreactivity.getCurrentTaxNo());
            }
            return ajaxResult;
        } catch (BaseException e) {
            e.printStackTrace();
            ajaxResult.put("checkCode", 0);
            ajaxResult.put("checkMessage", "无法链接到数电，请联系管理员！");
        }
        return ajaxResult;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
